package com.syh.jn.scm.infrastructure.repository.impl.upstream.system;

import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.infrastructure.repository.AbstractAggregateRepository;
import com.syh.jn.scm.domain.upstream.entity.system.UpAccount;
import com.syh.jn.scm.domain.upstream.repository.system.UpAccountOfPhoneReadRepository;
import com.syh.jn.scm.domain.upstream.repository.system.UpAccountRepository;
import com.syh.jn.scm.dto.upstream.system.upAccount.UpAccountVo;
import com.syh.jn.scm.infrastructure.repository.model.system.AccountModel;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import com.syh.jn.scm.infrastructure.wrapper.BaseResolve;
import com.syh.jn.scm.infrastructure.wrapper.ResolveToSQL;
import org.apache.ibatis.jdbc.SQL;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

@Repository
public class UpAccountRepositoryImpl extends AbstractAggregateRepository<UpAccount, AccountModel, Long> implements UpAccountRepository {

	@Resource(name = "upAccountOfPhoneReadRepositoryImpl")
	private UpAccountOfPhoneReadRepository upAccountOfPhoneReadRepository;

	@Override
	protected Class getViewObject() {
		return UpAccountVo.class;
	}

	@Override
	protected BaseResolve getViewWrapperResolve(Wrapper wrapper) {
		Map<String, String> params = new HashMap<>();
		params.put("loginAccount", "account.LOGIN_ACCOUNT");
		params.put("businessEntityId", "account.BUSINESS_ENTITY_ID");
		params.put("telephone", "account.TELEPHONE");
		params.put("enable", "account.ENABLE");
		params.put("roleId", "account.ROLE_ID");
		params.put("name", "account.NAME");
		params.put("terminalType", "account.TERMINAL_TYPE");
		params.put("id", "account.ID");
		params.put("loginPhoneId", "account.LOGIN_PHONE_ID");
		ResolveToSQL parse = new ResolveToSQL(wrapper, (propertyName) -> {
			return params.get(propertyName);
		});
		return parse;
	}

	@Override
	protected SQL getViewSql() {
		return new SQL() {{
			SELECT(
							SQLAliasGenerateUtil.aliasGenerate(AccountModel.class, "account", null),
							"role.ROLE_NAME AS roleName",
							"upstream.NAME AS businessEntityName"
			);
			FROM("T_SYSTEM_ACCOUNT account");
			LEFT_OUTER_JOIN("T_SYSTEM_ROLE role ON role.ID = account.ROLE_ID ");
			LEFT_OUTER_JOIN("T_BASE_UPSTREAM upstream ON upstream.ID = account.BUSINESS_ENTITY_ID ");
		}};
	}

	@Override
	public UpAccount getOne(Wrapper wrapper) {
		wrapper.append(Restrictions.eq("terminalType", "UPSTREAM"));
		return super.getOne(wrapper);
	}

	@Override
	public UpAccountVo getOneView(Wrapper wrapper) {
		wrapper.append(Restrictions.eq("terminalType", "UPSTREAM"));
		UpAccountVo vo = super.getOneView(wrapper);
		if(vo != null && vo.getLoginPhoneId() != null){
			Wrapper we = Wrapper.build().append(Restrictions.eq("id",vo.getLoginPhoneId()));
			vo.setLoginPhone(upAccountOfPhoneReadRepository.getOne(we));
		}
		return vo;
	}

	@Override
	public Short getAdminById(Long id) {
		AccountModel model = this.hibernateTemplate.get(AccountModel.class, id);
		if (model != null) {
			return model.getAdmin();
		}
		return null;
	}

	@Override
	public Long getCountByAccountName(String accountName) {
		String hql = "select count(*) from AccountModel model where model.loginAccount = :accountName";
		Query query = this.buildQuery(hql);
		query.setString("accountName", accountName);

		return (Long) query.uniqueResult();
	}

	@Override
	public Long getCountByAccountName(String accountName, Long excludeId) {
		String hql = "select count(*) from AccountModel model where model.loginAccount = :accountName and model.id !=:excludeId";
		Query query = this.buildQuery(hql);
		query.setString("accountName", accountName);
		query.setBigInteger("excludeId",BigInteger.valueOf(excludeId));

		return (Long) query.uniqueResult();
	}
}
